package com.yu.proxy;

import com.yu.service.RpcServiceProperties;
import com.yu.transfer.RpcRequest;
import com.yu.transfer.RpcResponse;
import com.yu.transport.client.RpcRequestTransport;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

/**
 * @PackageName: com.yu.proxy
 * @Description: 动态代理类
 * @Version: v1.0.0
 * @Author: yuweilin
 * @Date: 11:49
 * <p>
 * Modification History:
 * Date         Author          Version            Description
 * ------------------------------------------------------------
 * 2021/1/25      yuweilin         v1.0.0               新建
 */
@Slf4j
public class RpcClientProxy implements InvocationHandler {

    private final RpcRequestTransport rpcRequestTransport;
    private final RpcServiceProperties rpcServiceProperties;

    public RpcClientProxy(RpcRequestTransport rpcRequestTransport, RpcServiceProperties rpcServiceProperties) {
        this.rpcRequestTransport = rpcRequestTransport;
        if (rpcServiceProperties.getGroup()==null){
            rpcServiceProperties.setGroup("");
        }
        if (rpcServiceProperties.getVersion()==null){
            rpcServiceProperties.setVersion("");
        }
        this.rpcServiceProperties=rpcServiceProperties;
    }
    public RpcClientProxy(RpcRequestTransport rpcRequestTransport){
        this.rpcRequestTransport = rpcRequestTransport;
        this.rpcServiceProperties = RpcServiceProperties.builder().version("").group("").build();
    }

    /** transfer
     * 生成目标接口的代理类
     * @param clazz
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clazz){
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
    }

    private void check(RpcResponse<Object> rpcResponse, RpcRequest request){
        if (rpcResponse==null){
            throw new RuntimeException("服务调用失败");
        }
        if (!request.getRequestId().equals(rpcResponse.getRequestId())){
            throw new RuntimeException("请求和响应不匹配");
        }
        if (rpcResponse.getCode()==null||!rpcResponse.getCode().equals(200)){
            throw new RuntimeException("服务调用失败");
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("invoke method[{}]",method.getName());
        RpcRequest request = RpcRequest.builder()
                .methodName(method.getName())
                .parameters(args)
                .interfaceName(method.getDeclaringClass().getName())
                .paramTypes(method.getParameterTypes())
                .requestId(UUID.randomUUID().toString())
                .group(rpcServiceProperties.getGroup())
                .version(rpcServiceProperties.getVersion()).build();
        RpcResponse<Object> rpcResponse = null;
        CompletableFuture<RpcResponse<Object>> future = (CompletableFuture<RpcResponse<Object>>) rpcRequestTransport.sendRpcRequest(request);
        rpcResponse = future.get();
        this.check(rpcResponse,request);
        return rpcResponse.getData();
    }
}
